Properties in Python
property 初探
Properties 通常用于把公开的属性变成使用读值方法和设值方法管理的属性,且在不影响客户端代码的前提下实施业务规则。
|
|
|
|
10
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-9-68054ba7debc> in <module>()
1 walnuts_valid = LineItem('walnuts_valid',10,10)
2 print(walnuts_valid.weight)
----> 3 walnuts_invalid = LineItem('walnuts_invalid', 0, 10.00)
<ipython-input-8-2cd43540d5e1> in __init__(self, description, weight, price)
2 def __init__(self, description, weight, price):
3 self.description = description
----> 4 self.weight = weight
5 self.price = price
6
<ipython-input-8-2cd43540d5e1> in weight(self, value)
19 self.__weight = value
20 else:
---> 21 raise ValueError('value must be > 0')
ValueError: value must be > 0
如上所示,我们使用property禁止了用户为 weight 属性提供负值或零。值得注意的是,如果一个属性只有读值方法而没有设值方法,那么该属性就是只读属性,对其赋值的操作是不被允许的。
深入理解 property
虽然内置的property经常用于装饰器,但是其实它是一个类。而Python中,函数和类通常可以互换。property构造方法的完整签名如下:
|
|
其所有参数均是可选的,如果没有把某个函数传递给某个参数,那么得到的特性对象就不允许执行相应操作。
下面是一个不使用装饰器定义的经典方法。
|
|
|
|
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-11-2126031d851a> in <module>()
1 walnuts_valid = LineItem('walnuts_valid',10,10)
----> 2 walnuts_invalid = LineItem('walnuts_invalid', 0, 10.00)
<ipython-input-10-74ad4ef73232> in __init__(self, description, weight, price)
2 def __init__(self, description, weight, price):
3 self.description = description
----> 4 self.weight = weight
5 self.price = price
6
<ipython-input-10-74ad4ef73232> in set_weight(self, value)
17 self.__weight = value
18 else:
---> 19 raise ValueError('value must be > 0')
20 weight = property(fget=get_weight, fset = set_weight)
ValueError: value must be > 0
property会覆盖实例属性
特性都是类属性,但是特性管理的其实是实例属性的存取。如果实例和所属的类具有同名数据属性,那么实例属性会覆盖类属性。但是实例属性不会遮盖类特性。新添加的类特性会遮盖现有的实例属性。
为property添加文档
对于经典调用句法,只需要对property函数传入doc参数即可。对于装饰器用法,读值方法的文档字符串作为特性的文档。
特性工厂函数
LineItem类存在一个问题,如果其有多个属性需要做限制,那么我们将需要写若干个读值和设值方法来达到目的,而这些方法实际上都是类似的,显得有些麻烦。而借助特性工厂函数,我们可以不用手动实现这样若干对几乎一致的读值和设值方法。
|
|
参考
1、Fluent Python by Luciano Ramalho (O’Reilly). Copyright 2015 Luciano Ramalho, 978-1-491-94600-8
2、廖雪峰Python教程—@property